<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>圆形进度条效果</title>
  <style>
    .box {
      position: absolute;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      margin: auto;
    }
    /* 进度条 */
    .progress {
      /* 注：使用 document.querySelector('.progress').getTotalLength() 可以得到圆一圈大小约为377 */
      /* stroke-dasharray: 377; */
      /* stroke-dashoffset 表示当前进度条剩余长度
        为 0 时表示进度条已完成，最大为 stroke-dasharray 的值，等于 stroke-dasharray 的值 时表示进度为 0
        我们可以使用 js 动态更新这个值得到进度逐步增加的效果
      */
      /* stroke-dashoffset: 377; */
    }
  </style>
</head>
<body>
  <!-- 最外层的盒子 使用 svg 格式绘制图形 -->
  <svg class="box" width="200" height="200">
    <!-- 定义一个线性渐变色 -->
    <defs>
      <linearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="0%">
        <stop offset="0%" style="stop-color:rgb(57, 242, 218);stop-opacity:1" />
        <stop offset="50%" style="stop-color:rgb(6, 166, 230);stop-opacity:1" />
        <stop offset="100%" style="stop-color:hsl(223, 92%, 50%);stop-opacity:1" />
      </linearGradient>
    </defs>
    <!-- circle用于定义圆形进度条 -->
    <circle class="progress" cx="100" cy="100" r="60" fill="transparent" stroke="url(#grad1)" stroke-width="10"></circle>
    <!-- 内部的文本 -->
    <text class="text" x="100" y="100" fill="#0c4ef5" text-anchor="middle" alignment-baseline="middle"></text>
  </svg>
  <script>
    // 获取进度条元素
    const progress = document.querySelector('.progress')
    const text = document.querySelector('.text')  // 获取内部的文本元素
    // 获取圆一整圈的长度
    const maxLen = Math.ceil(progress.getTotalLength())   // 结果可向上取整
    progress.style.strokeDasharray = maxLen
    console.log(maxLen);

    // 效果1：自定义进度 teep 条
    // 定义的进度效果列表（注：表示的是百分比的值)
    /* const loadings = [5, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
    let loadingIndex = 0
    const timer = setInterval(() => {
      progress.style.strokeDashoffset = maxLen - (loadings[loadingIndex] / 100 * maxLen)
      loadingIndex += 1
      text.innerHTML = `${loadings[loadingIndex]}%`
      // 进度列表的值取完就停止定时器
      if(loadingIndex === loadings.length) {
        clearInterval(timer)
        text.innerHTML = `OK`
      }
    }, 200);   // 注：间隔时间越短进度条越丝滑
    */

    // 效果2：匀速从 0~100% 的进度效果
    let num = maxLen   // 进度条的初始值,效果为进度条为 0
    // 此类场景使用 window.requestAnimationFrame() 进行循环比使用定时器性能更好
     let timer = window.requestAnimationFrame( function fn() {
      // 循环继续的条件
      if(num > 0) {
        num -= 2    // 减得越小动画持续时间越长
        progress.style.strokeDashoffset = num
        text.innerHTML = ((1 - num / maxLen) * 100).toFixed() + '%'
        // 继续循环则递归调用 fn 函数
        timer = window.requestAnimationFrame(fn)
      } else {
        // 循环停止
        progress.style.strokeDashoffset = 0
        // 清除定时器
        window.cancelAnimationFrame(timer)
      }
    })


  </script>
</body>
</html>